package com.balabala.gym_goods.service.impl;

import com.balabala.exception.CustomerException;
import com.balabala.gym_enum.ExceptionEnum;
import com.balabala.gym_goods.constant.SkuConstant;
import com.balabala.gym_goods.mapper.SkuMapper;
import com.balabala.goods.pojo.dto.LockStockDTO;
import com.balabala.gym_goods.pojo.entity.Sku;
import com.balabala.gym_goods.service.SkuService;
import com.balabala.result.Result;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 *
 * @author 何涛
 * @date 2023/5/8 0008
 */

@Service
@Slf4j
public class SkuServiceImpl extends ServiceImpl<SkuMapper, Sku> implements SkuService {

    @Autowired
    RedisTemplate redisTemplate;


    @Override
    public Result batchLockStock(List<LockStockDTO> lockStockDTOS) {
        log.info("=======================创建订单，开始锁定商品库存=======================");
        if(CollectionUtils.isEmpty(lockStockDTOS))
        {
            log.info("没有要锁定的库存");
            throw new CustomerException(ExceptionEnum.NO_LOCK_STOCK);
        }

        // 批量锁定库存
        // todo 开启分布式锁
        lockStockDTOS.forEach(lockStockDTO ->
            lockStockDTO.setIsLock(
                    update( new LambdaUpdateWrapper<Sku>()
                        .eq(Sku::getId,lockStockDTO.getSkuId())
                        .setSql("lock_stock=lock_stock + "+lockStockDTO.getCount())
                        .apply("stock - lock_stock > {0}",lockStockDTO.getCount())
            )));
        //获取锁定库存失败的集合
        List<LockStockDTO> unLockStockList = lockStockDTOS.stream().filter(lockStockDTO -> !lockStockDTO.getIsLock()).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(unLockStockList))
        {
            log.info("库存不足，恢复以上锁库存的数据");
            //获取以上锁的sku集合
            List<LockStockDTO> lockStockDTOList = lockStockDTOS.stream().filter(lockStockDTO -> lockStockDTO.getIsLock()).collect(Collectors.toList());
            lockStockDTOList.forEach(lockStockDTO -> update(new LambdaUpdateWrapper<Sku>()
                    .eq(Sku::getId,lockStockDTOS)
                    .setSql("lock_stock=lock_stock -"+lockStockDTO.getCount())));
            //提示哪些sku库存不足
            return Result.fail(444,"商品库存不足："+unLockStockList.toString());
        }
        //把锁定的库存放到redis中
        redisTemplate.boundValueOps(SkuConstant.LOCK_STOCK_PREFIX+lockStockDTOS.get(0).getOrderToken()).set(lockStockDTOS);
        log.info("redis中锁定商品信息：{}", lockStockDTOS.toString());

        // todo 释放分布式锁
        return Result.ok();
    }

    @Override
    public Boolean unLockStock(String orderSn) {
        log.info("=======================取消订单，开始释放库存=======================");
        List<LockStockDTO> lockStockDTOList= (List<LockStockDTO>) redisTemplate.boundValueOps(SkuConstant.LOCK_STOCK_PREFIX + orderSn).get();
        lockStockDTOList.forEach(lockStockDTO ->
                update(new LambdaUpdateWrapper<Sku>()
                        .setSql("lock_stock=lock_sock -"+lockStockDTO.getCount())
                        .eq(Sku::getId,lockStockDTO.getSkuId())
                )
        );

        //删除redis中的锁定库存
        redisTemplate.boundValueOps(SkuConstant.LOCK_STOCK_PREFIX+orderSn).expire(-1, TimeUnit.SECONDS);
        return true;
    }
}
